﻿#include "drawobj.h"
#include <QPainter>
#include <QLinearGradient>
#include <QRadialGradient>
#include <QCursor>
#include <QDebug>
#include <QGraphicsEffect>
#include <QMatrix4x4>
#include <QGraphicsTransform>
#include <QStyle>
#include <QRectF>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsEllipseItem>
#include <QLineF>
#include <cmath>
#include "drawscene.h"
#include "drawview.h"
#include <QMenu>
#include <QDateTime>

static int count = 0;

ShapeMimeData::ShapeMimeData(QList<QGraphicsItem *> items)
{
    foreach (QGraphicsItem *item , items ) {
       AbstractShape *sp = qgraphicsitem_cast<AbstractShape*>(item);
       m_items.append(sp->duplicate());
    }
}
ShapeMimeData::~ShapeMimeData()
{
    foreach (QGraphicsItem *item , m_items ) {
        delete item;
    }
    m_items.clear();
}

QList<QGraphicsItem *> ShapeMimeData::items() const
{
    return m_items;
}

static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen)
{
    const qreal penWidthZero = qreal(0.00000001);

    if (path == QPainterPath() || pen == Qt::NoPen)
        return path;
    QPainterPathStroker ps;
    ps.setCapStyle(pen.capStyle());
    if (pen.widthF() <= 0.0)
        ps.setWidth(penWidthZero);
    else
        ps.setWidth(pen.widthF());
    ps.setJoinStyle(pen.joinStyle());
    ps.setMiterLimit(pen.miterLimit());
    QPainterPath p = ps.createStroke(path);
    p.addPath(path);
    return p;
}

static void qt_graphicsItem_highlightSelected(
    QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
{
    const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
    if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
        return;

    const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
    if (qMin(mbrect.width(), mbrect.height()) < qreal(1.0))
        return;

    qreal itemPenWidth;
    switch (item->type()) {
        case QGraphicsEllipseItem::Type:
            itemPenWidth = static_cast<QGraphicsEllipseItem *>(item)->pen().widthF();
            break;
        case QGraphicsPathItem::Type:
            itemPenWidth = static_cast<QGraphicsPathItem *>(item)->pen().widthF();
            break;
        case QGraphicsPolygonItem::Type:
            itemPenWidth = static_cast<QGraphicsPolygonItem *>(item)->pen().widthF();
            break;
        case QGraphicsRectItem::Type:
            itemPenWidth = static_cast<QGraphicsRectItem *>(item)->pen().widthF();
            break;
        case QGraphicsSimpleTextItem::Type:
            itemPenWidth = static_cast<QGraphicsSimpleTextItem *>(item)->pen().widthF();
            break;
        case QGraphicsLineItem::Type:
            itemPenWidth = static_cast<QGraphicsLineItem *>(item)->pen().widthF();
            break;
        default:
            itemPenWidth = 1.0;
    }
    const qreal pad = itemPenWidth / 2;

    const qreal penWidth = 0; // cosmetic pen

    const QColor fgcolor = option->palette.windowText().color();
    const QColor bgcolor( // ensure good contrast against fgcolor
        fgcolor.red()   > 127 ? 0 : 255,
        fgcolor.green() > 127 ? 0 : 255,
        fgcolor.blue()  > 127 ? 0 : 255);


    painter->setPen(QPen(bgcolor, penWidth, Qt::SolidLine));
    painter->setBrush(Qt::NoBrush);
    painter->drawRect(item->boundingRect().adjusted(-pad, -pad, pad, pad));

    painter->setPen(QPen(QColor("lightskyblue"), 0, Qt::SolidLine));
    painter->setBrush(Qt::NoBrush);
    painter->drawRect(item->boundingRect().adjusted(-pad, -pad, pad, pad));

}

GraphicsItem::GraphicsItem(QGraphicsItem *parent)
    :AbstractShapeType<QGraphicsItem>(parent)
{
    // handles
    m_handles.reserve(Left);
    for (int i = LeftTop; i <= Left; ++i) {
        SizeHandleRect *shr = new SizeHandleRect(this,i);
        m_handles.push_back(shr);
    }

    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
    this->setAcceptHoverEvents(true);
}


QPixmap GraphicsItem::image() {
    QPixmap pixmap(64, 64);
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    setPen(QPen(Qt::black));
    setBrush(Qt::white);
    QStyleOptionGraphicsItem *styleOption = new QStyleOptionGraphicsItem;
//    painter.translate(m_localRect.center().x(),m_localRect.center().y());
    paint(&painter,styleOption);
    delete styleOption;
    return pixmap;
}


void GraphicsItem::updatehandles()
{
    const QRectF &geom = this->boundingRect();

    const Handles::iterator hend =  m_handles.end();
    for (Handles::iterator it = m_handles.begin(); it != hend; ++it)
    {
        SizeHandleRect *hndl = *it;;
        switch (hndl->dir())
        {
        case LeftTop:
            hndl->move(geom.x() , geom.y() );
            break;
        case Top:
            hndl->move(geom.x() + geom.width() / 2 , geom.y() );
            break;
        case RightTop:
            hndl->move(geom.x() + geom.width() , geom.y() );
            break;
        case Right:
            hndl->move(geom.x() + geom.width() , geom.y() + geom.height() / 2 );
            break;
        case RightBottom:
            hndl->move(geom.x() + geom.width() , geom.y() + geom.height() );
            break;
        case Bottom:
            hndl->move(geom.x() + geom.width() / 2 , geom.y() + geom.height() );
            break;
        case LeftBottom:
            hndl->move(geom.x(), geom.y() + geom.height());
            break;
        case Left:
            hndl->move(geom.x(), geom.y() + geom.height() / 2);
            break;
        default:
            break;
        }
    }
}

//void GraphicsItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
//{
//    Q_UNUSED(event);
//}

QVariant GraphicsItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    if ( change == QGraphicsItem::ItemSelectedHasChanged ) {
        QGraphicsItemGroup *g = dynamic_cast<QGraphicsItemGroup*>(parentItem());
        if (!g)
            setState(value.toBool() ? SelectionHandleActive : SelectionHandleOff);
        else{
            setSelected(false);
            return QVariant::fromValue<bool>(false);
        }
    }
    return QGraphicsItem::itemChange(change, value);
}


GraphicsRectItem::GraphicsRectItem(const QRect & rect , QGraphicsItem *parent)
    :GraphicsItem(parent)
    ,m_fRatioX(1/10.0)
    ,m_fRatioY(1/3.0)
    ,m_unit(Unit())
    ,startConnectLineItems(new QList<GraphicsConnectLineItem*>)
    ,endConnectLineItems(new QList<GraphicsConnectLineItem*>)
{
    setFlag(ItemClipsChildrenToShape, false);
    m_width = rect.width();
    m_height = rect.height();
    m_initialRect = rect;
    m_localRect = m_initialRect;
    m_localRect = rect;
    m_originPoint = QPointF(0,0);
    updatehandles();
}

GraphicsRectItem::~GraphicsRectItem()
{
    delete m_pinPointGroup;
}

void GraphicsRectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    if (event->reason() != QGraphicsSceneContextMenuEvent::Mouse || scene()->views().isEmpty())
        return;

    DrawView* drawView = dynamic_cast<DrawView*>(scene()->views()[0]);
    setSelected(true);
    if(!drawView)
        return;
    drawView->showContextMenu(this, event->screenPos());
    event->accept();
}

QRectF GraphicsRectItem::boundingRect() const
{
    return m_localRect;
}

QPainterPath GraphicsRectItem::shape() const
{
    QPainterPath path;
    double rx,ry;
    m_fRatioX <=0 ? rx=0 : rx = m_width * m_fRatioX + 0.5;
    m_fRatioY <=0 ? ry = 0 : ry = m_height * m_fRatioY + 0.5;
    path.addRect(rect());
    return path;
}

void GraphicsRectItem::control(int dir, const QPointF & delta)
{
    QPointF local = mapFromParent(delta);
    switch (dir) {
    case 9:
    {
        QRectF delta1 = rect();
        int y = local.y();
        if(y> delta1.center().y() )
            y = delta1.center().y();
        if(y<delta1.top())
            y=delta1.top();
        int H= delta1.height();
        if(H==0)
            H=1;
        m_fRatioY = std::abs(((float)(delta1.top()-y)))/H;
    }
        break;
    case 10:
    {
        QRectF delta1 = rect();
        int x = local.x();
        if(x < delta1.center().x() )
            x = delta1.center().x();
        if(x>delta1.right())
            x=delta1.right();
        int W= delta1.width();
        if(W==0)
            W=1;
        m_fRatioX = std::abs(((float)(delta1.right()-x)))/W;
        break;
    }
    case 11:
    {
        m_originPoint = local;
    }
        break;
   default:
        break;
    }
    prepareGeometryChange();
    updatehandles();
}

void GraphicsRectItem::stretch(int handle , double sx, double sy, const QPointF & origin)
{
    QTransform trans  ;
    switch (handle) {
    case Right:
    case Left:
        sy = 1;
        break;
    case Top:
    case Bottom:
        sx = 1;
        break;
    default:
        break;
    }

    opposite_ = origin;

    trans.translate(origin.x(),origin.y());
    trans.scale(sx,sy);
    trans.translate(-origin.x(),-origin.y());

    prepareGeometryChange();
    m_localRect = trans.mapRect(m_initialRect);
    m_width = m_localRect.width();
    m_height = m_localRect.height();
    updatehandles();

}

void GraphicsRectItem::updateCoordinate()
{

    QPointF pt1,pt2,delta;

    pt1 = mapToScene(transformOriginPoint());
    pt2 = mapToScene(m_localRect.center());
    delta = pt1 - pt2;

    if (!parentItem() ){
        prepareGeometryChange();
        m_localRect = QRectF(-m_width/2,-m_height/2,m_width,m_height);
        m_width = m_localRect.width();
        m_height = m_localRect.height();
        setTransform(transform().translate(delta.x(),delta.y()));
        setTransformOriginPoint(m_localRect.center());
        moveBy(-delta.x(),-delta.y());
        setTransform(transform().translate(-delta.x(),-delta.y()));
        opposite_ = QPointF(0,0);
        updatehandles();
    }
    m_initialRect = m_localRect;
}

void GraphicsRectItem::move(const QPointF &point)
{
    moveBy(point.x(),point.y());
}

QGraphicsItem *GraphicsRectItem::duplicate() const
{
    GraphicsRectItem * item = new GraphicsRectItem(rect().toRect());
    item->m_width = width();
    item->m_height = height();
    item->setPos(pos().x(),pos().y());
    item->setPen(pen());
    item->setBrush(brush());
    item->setTransform(transform());
    item->setTransformOriginPoint(transformOriginPoint());
    item->setRotation(rotation());
    item->setScale(scale());
    item->setZValue(zValue()+0.1);
    item->m_fRatioY = m_fRatioY;
    item->m_fRatioX = m_fRatioX;
    item->updateCoordinate();
    item->setPixmap(m_pixmap);
    item->setUnit(m_unit);
    item->updateUnitInfo();
    QDateTime currentTime = QDateTime::currentDateTime();
    item->getUnit().id = item->getUnit().name + currentTime.toString("yyyyMMddHHmmsszzz");
    return item;
}

void GraphicsRectItem::setUnit(const Unit u)
{
    m_unit = u;
    if(!m_pinPointGroup)
        m_pinPointGroup = new PinPointHandleGroup(m_unit, this);
    else
        m_pinPointGroup->updatePinPointHandle(this);
//    for(auto it : *startConnectLineItems)
//        delete it;
//    for(auto it : *endConnectLineItems)
//        delete it;
    updatePinPointHandles();
}

void GraphicsRectItem::updateUnitInfo()
{
    m_unit.pos.x = QString::number((int)pos().x());
    m_unit.pos.y = QString::number((int)pos().y());
    m_unit.pos.w = QString::number((int)rect().width());
    m_unit.pos.h = QString::number((int)rect().height());
    m_unit.pos.angle = QString::number(rotation());
}

void GraphicsRectItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    count++;
}

PinPointHandle *GraphicsRectItem::getClickPin(QPointF clickPos)
{
    return m_pinPointGroup ? m_pinPointGroup->getClickPin(clickPos) : nullptr;
}

PinPointHandle *GraphicsRectItem::getPinFormPinIndex(int index)
{
    return m_pinPointGroup ? m_pinPointGroup->getPinFormPinIndex(index) : nullptr;
}

void GraphicsRectItem::updateConnectLineTool()
{
    for(GraphicsConnectLineItem* it : *startConnectLineItems)
    {
        if(!it || !it->getPivotTool()->getEndPin() || !it->scene())
            continue;
        ConnectLineItemPivotTool* pivotTool = it->getPivotTool();
        pivotTool->setStartPoint(pivotTool->getStartPin()->getPos());
        pivotTool->setEndPoint(it->parentItem()->mapFromScene(pivotTool->getEndPin()->scenePos()));
        pivotTool->calculatePivotPoints(pivotTool->getStartPin(), pivotTool->getEndPoint());
        it->initMidRects();
    }

    for(GraphicsConnectLineItem* it : *endConnectLineItems)
    {
        if(!it || !it->getPivotTool()->getEndPin() || !it->scene())
            continue;
        ConnectLineItemPivotTool* pivotTool = it->getPivotTool();
        pivotTool->setStartPoint(pivotTool->getStartPin()->getPos());
        pivotTool->setEndPoint(it->parentItem()->mapFromScene(pivotTool->getEndPin()->scenePos()));
        pivotTool->calculatePivotPoints(pivotTool->getStartPin(), pivotTool->getEndPoint());
        it->initMidRects();
    }
}

void GraphicsRectItem::updatehandles()
{
    GraphicsItem::updatehandles();
    updatePinPointHandles();
}

void GraphicsRectItem::updatePinPointHandles()
{
    const QRectF &geom=this->boundingRect();
    if(!m_pinPointGroup)
        return;
    m_pinPointGroup->movePins(Direction::Down, geom);
    m_pinPointGroup->movePins(Direction::Left, geom);
    m_pinPointGroup->movePins(Direction::Up, geom);
    m_pinPointGroup->movePins(Direction::Right, geom);
}

QRectF RecalcBounds(const QPolygonF&  pts)
{
    QRectF bounds(pts[0], QSize(0, 0));
    for (int i = 1; i < pts.count(); ++i)
    {
        if (pts[i].x() < bounds.left())
            bounds.setLeft(pts[i].x());
        if (pts[i].x() > bounds.right())
            bounds.setRight(pts[i].x());
        if (pts[i].y() < bounds.top())
            bounds.setTop(pts[i].y());
        if (pts[i].y() > bounds.bottom())
            bounds.setBottom (pts[i].y());
    }
    bounds = bounds.normalized();
    return bounds;
}

void GraphicsRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->save();
    painter->setPen(Qt::black);
    painter->drawRect(rect().toRect());

    if (!m_pixmap.isNull())
    {
        QPixmap flippedPixmap = m_pixmap.transformed(QTransform().scale(1, -1));
        painter->setCompositionMode(QPainter::CompositionMode_Source); //修改图片混合模式不与背景合并
        painter->drawPixmap(rect().toRect(), flippedPixmap);

        QFont font("Arial", 12);
        font.setBold(true);
        painter->setFont(font);
        painter->setPen(Qt::blue);

        painter->save();
        painter->scale(1, -1);
        QRectF flippedRect = rect();
        flippedRect.moveTop(-flippedRect.bottom());
        painter->drawText(flippedRect.toRect(), Qt::AlignTop | Qt::AlignHCenter, m_unit.id);
        painter->restore();
    }
    painter->restore();
}

GraphicsItemGroup::GraphicsItemGroup(QGraphicsItem *parent)
    :AbstractShapeType <QGraphicsItemGroup>(parent),
      m_parent(parent)
{
    itemsBoundingRect = QRectF();
    // handles
    m_handles.reserve(Left);
    for (int i = LeftTop; i <= Left; ++i) {
        SizeHandleRect *shr = new SizeHandleRect(this, i);
        m_handles.push_back(shr);
    }
    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
    this->setAcceptHoverEvents(true);
}


QRectF GraphicsItemGroup::boundingRect() const
{
    return itemsBoundingRect;
}

GraphicsItemGroup::~GraphicsItemGroup()
{

}

QGraphicsItem *GraphicsItemGroup::duplicate() const
{
    GraphicsItemGroup *item = 0;
    QList<QGraphicsItem*> copylist = duplicateItems();
    item = createGroup(copylist);
    item->setPos(pos().x(),pos().y());
    item->setPen(pen());
    item->setBrush(brush());
    item->setTransform(transform());
    item->setTransformOriginPoint(transformOriginPoint());
    item->setRotation(rotation());
    item->setScale(scale());
    item->setZValue(zValue()+0.1);
    item->updateCoordinate();
    item->m_width = m_width;
    item->m_height = m_height;
    return item;
}

void GraphicsItemGroup::control(int dir, const QPointF &delta)
{
    QPointF local = mapFromParent(delta);
    if ( dir < Left ) return ;
    if ( dir == 9 ) {
    }
    updatehandles();
}

void GraphicsItemGroup::stretch(int handle, double sx, double sy, const QPointF &origin)
{
    QTransform trans ;
    switch (handle)
    {
        case Right:
        case Left:
            sy = 1;
            break;
        case Top:
        case Bottom:
            sx = 1;
            break;
        default:
            break;
    }

    foreach (QGraphicsItem *item , childItems())
    {
         AbstractShape * ab = qgraphicsitem_cast<AbstractShape*>(item);
         if (ab && !qgraphicsitem_cast<SizeHandleRect*>(ab))
             ab->stretch(handle,sx,sy,ab->mapFromParent(origin));
    }

    trans.translate(origin.x(),origin.y());
    trans.scale(sx,sy);
    trans.translate(-origin.x(),-origin.y());

    prepareGeometryChange();
    itemsBoundingRect = trans.mapRect(m_initialRect);
    m_width = itemsBoundingRect.width();
    m_height = itemsBoundingRect.height();
    updatehandles();

}

void GraphicsItemGroup::updateCoordinate()
{

    QPointF pt1,pt2,delta;
    if (itemsBoundingRect.isNull() )
        itemsBoundingRect = QGraphicsItemGroup::boundingRect();

    pt1 = mapToScene(transformOriginPoint());
    pt2 = mapToScene(itemsBoundingRect.center());
    delta = pt1 - pt2;
    m_initialRect = itemsBoundingRect;
    m_width = itemsBoundingRect.width();
    m_height = itemsBoundingRect.height();
    setTransform(transform().translate(delta.x(),delta.y()));
    setTransformOriginPoint(itemsBoundingRect.center());
    moveBy(-delta.x(),-delta.y());

    foreach (QGraphicsItem *item , childItems()) {
         AbstractShape * ab = qgraphicsitem_cast<AbstractShape*>(item);
         if (ab && !qgraphicsitem_cast<SizeHandleRect*>(ab))
             ab->updateCoordinate();
    }
    updatehandles();
}

GraphicsItemGroup *GraphicsItemGroup::createGroup(const QList<QGraphicsItem *> &items) const
{
    QList<QGraphicsItem *> ancestors;
    int n = 0;
    if (!items.isEmpty())
    {
        QGraphicsItem *parent = items.at(n++);
        while ((parent = parent->parentItem()))
            ancestors.append(parent);
    }

    // Find the common ancestor for all items
    QGraphicsItem *commonAncestor = 0;
    if (!ancestors.isEmpty())
    {
        while (n < items.size())
        {
            int commonIndex = -1;
            QGraphicsItem *parent = items.at(n++);
            do {
                int index = ancestors.indexOf(parent, qMax(0, commonIndex));
                if (index != -1) {
                    commonIndex = index;
                    break;
                }
            } while ((parent = parent->parentItem()));

            if (commonIndex == -1) {
                commonAncestor = 0;
                break;
            }

            commonAncestor = ancestors.at(commonIndex);
        }
    }
    GraphicsItemGroup *group = new GraphicsItemGroup(commonAncestor);
    foreach (QGraphicsItem *item, items){
        item->setSelected(false);
        QGraphicsItemGroup *g = dynamic_cast<QGraphicsItemGroup*>(item->parentItem());
        if ( !g )
             group->addToGroup(item);
    }
    return group;
}

QList<QGraphicsItem *> GraphicsItemGroup::duplicateItems() const
{
    QList<QGraphicsItem*> copylist ;
    foreach (QGraphicsItem * shape , childItems() ) {
        AbstractShape * ab = qgraphicsitem_cast<AbstractShape*>(shape);
        if ( ab && !qgraphicsitem_cast<SizeHandleRect*>(ab)){
            QGraphicsItem * cp = ab->duplicate();
            copylist.append(cp);
        }
    }
    return copylist;
}

void GraphicsItemGroup::updatehandles()
{
    const QRectF &geom = this->boundingRect();

    const Handles::iterator hend =  m_handles.end();
    for (Handles::iterator it = m_handles.begin(); it != hend; ++it)
    {
        SizeHandleRect *hndl = *it;;
        switch (hndl->dir())
        {
            case LeftTop:
                hndl->move(geom.x() , geom.y() );
                break;
            case Top:
                hndl->move(geom.x() + geom.width() / 2 , geom.y() );
                break;
            case RightTop:
                hndl->move(geom.x() + geom.width() , geom.y() );
                break;
            case Right:
                hndl->move(geom.x() + geom.width() , geom.y() + geom.height() / 2 );
                break;
            case RightBottom:
                hndl->move(geom.x() + geom.width() , geom.y() + geom.height() );
                break;
            case Bottom:
                hndl->move(geom.x() + geom.width() / 2 , geom.y() + geom.height() );
                break;
            case LeftBottom:
                hndl->move(geom.x(), geom.y() + geom.height());
                break;
            case Left:
                hndl->move(geom.x(), geom.y() + geom.height() / 2);
                break;
            case 9:
                hndl->move(transformOriginPoint().x(),transformOriginPoint().y());
                break;
            default:
                break;
        }
    }
}

QVariant GraphicsItemGroup::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    if ( change == QGraphicsItem::ItemSelectedHasChanged ) {
        QGraphicsItemGroup *g = dynamic_cast<QGraphicsItemGroup*>(parentItem());
        if (!g)
            setState(value.toBool() ? SelectionHandleActive : SelectionHandleOff);
        else{
            setSelected(false);
            return QVariant::fromValue<bool>(false);
        }
        if( value.toBool()){
            updateCoordinate();
        }
    }

    return QGraphicsItemGroup::itemChange(change, value);
}

void GraphicsItemGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(widget);
    if (option->state & QStyle::State_Selected)
        qt_graphicsItem_highlightSelected(this, painter, option);
}

GraphicsPolygonItem::GraphicsPolygonItem(QGraphicsItem *parent)
    :GraphicsItem(parent)
{
    // handles
    m_points.clear();
    m_pen = QPen(Qt::black);
}

QRectF GraphicsPolygonItem::boundingRect() const
{
    return shape().controlPointRect();
}

QPainterPath GraphicsPolygonItem::shape() const
{
    QPainterPath path;
    path.addPolygon(m_points);
    path.closeSubpath();
    return qt_graphicsItem_shapeFromPath(path,pen());
}

void GraphicsPolygonItem::addPoint(const QPointF &point)
{
    m_points.append(mapFromScene(point));
    int dir = m_points.count();
    SizeHandleRect *shr = new SizeHandleRect(this, dir+Left, true);
    shr->setState(SelectionHandleActive);
    m_handles.push_back(shr);
}

void GraphicsPolygonItem::control(int dir, const QPointF &delta)
{
    QPointF pt = mapFromScene(delta);
    if ( dir <= Left ) return ;
    m_points[dir - Left -1] = pt;
    prepareGeometryChange();
    m_localRect = m_points.boundingRect();
    m_width = m_localRect.width();
    m_height = m_localRect.height();
    m_initialPoints = m_points;
    updatehandles();
}

void GraphicsPolygonItem::stretch(int handle, double sx, double sy, const QPointF &origin)
{
    QTransform trans;
    switch (handle)
    {
        case Right:
        case Left:
            sy = 1;
            break;
        case Top:
        case Bottom:
            sx = 1;
            break;
        default:
            break;
    }
    trans.translate(origin.x(),origin.y());
    trans.scale(sx,sy);
    trans.translate(-origin.x(),-origin.y());

    prepareGeometryChange();
    m_points = trans.map(m_initialPoints);
    m_localRect = m_points.boundingRect();
    m_width = m_localRect.width();
    m_height = m_localRect.height();
    updatehandles();
}

void GraphicsPolygonItem::updateCoordinate()
{

    QPointF pt1,pt2,delta;
    QPolygonF pts = mapToScene(m_points);
    if (parentItem()==NULL)
    {
        pt1 = mapToScene(transformOriginPoint());
        pt2 = mapToScene(boundingRect().center());
        delta = pt1 - pt2;

        for (int i = 0; i < pts.count() ; ++i )
            pts[i]+=delta;
        prepareGeometryChange();
        m_points = mapFromScene(pts);
        m_localRect = m_points.boundingRect();
        m_width = m_localRect.width();
        m_height = m_localRect.height();

        setTransform(transform().translate(delta.x(),delta.y()));
        moveBy(-delta.x(),-delta.y());
        setTransform(transform().translate(-delta.x(),-delta.y()));
        updatehandles();
    }
    m_initialPoints = m_points;

}

void GraphicsPolygonItem::endPoint(const QPointF & point)
{
    Q_UNUSED(point);
    int nPoints = m_points.count();
    if( nPoints > 2 && (m_points[nPoints-1] == m_points[nPoints-2] ||
        m_points[nPoints-1].x() - 1 == m_points[nPoints-2].x() &&
        m_points[nPoints-1].y() == m_points[nPoints-2].y())){
        delete m_handles[Left + nPoints-1];
        m_points.remove(nPoints-1);
        m_handles.resize(Left + nPoints-1);
    }
    m_initialPoints = m_points;
}

QGraphicsItem *GraphicsPolygonItem::duplicate() const
{
    GraphicsPolygonItem * item = new GraphicsPolygonItem( );
    item->m_width = width();
    item->m_height = height();
    item->m_points = m_points;

    for ( int i = 0 ; i < m_points.size() ; ++i )
        item->m_handles.push_back(new SizeHandleRect(item,Left+i+1,true));

    item->setPos(pos().x(),pos().y());
    item->setPen(pen());
    item->setBrush(brush());
    item->setTransform(transform());
    item->setTransformOriginPoint(transformOriginPoint());
    item->setRotation(rotation());
    item->setScale(scale());
    item->setZValue(zValue()+0.1);
    item->updateCoordinate();
    return item;
}

void GraphicsPolygonItem::updatehandles()
{
    GraphicsItem::updatehandles();

    for ( int i = 0 ; i < m_points.size() ; ++i ){
        m_handles[Left+i]->move(m_points[i].x() ,m_points[i].y() );
    }
}

void GraphicsPolygonItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    QColor c = brushColor();
    QLinearGradient result(boundingRect().topLeft(), boundingRect().topRight());
    result.setColorAt(0, c.dark(150));
    result.setColorAt(0.5, c.light(200));
    result.setColorAt(1, c.dark(150));
    painter->setBrush(result);

    painter->setPen(pen());
    painter->drawPolygon(m_points);

    if (option->state & QStyle::State_Selected)
        qt_graphicsItem_highlightSelected(this, painter, option);
}

GraphicsLineItem::GraphicsLineItem(QGraphicsItem *parent)
    :GraphicsPolygonItem(parent)
{
    m_pen = QPen(Qt::black);
    // handles
    m_handles.reserve(Left);

    Handles::iterator hend =  m_handles.end();
    for (Handles::iterator it = m_handles.begin(); it != hend; ++it)
       delete (*it);
    m_handles.clear();
}

QPainterPath GraphicsLineItem::shape() const
{
    QPainterPath path;
    if ( m_points.size() > 1 ){
        path.moveTo(m_points.at(0));
        path.lineTo(m_points.at(1));
    }
    return qt_graphicsItem_shapeFromPath(path,pen());
}

QGraphicsItem *GraphicsLineItem::duplicate() const
{
    GraphicsLineItem * item = new GraphicsLineItem();
    item->m_width = width();
    item->m_height = height();
    item->m_points = m_points;
    item->m_initialPoints = m_initialPoints;
    item->setPos(pos().x(),pos().y());
    item->setPen(pen());
    item->setBrush(brush());
    item->setTransform(transform());
    item->setTransformOriginPoint(transformOriginPoint());
    item->setRotation(rotation());
    item->setScale(scale());
    item->setZValue(zValue()+0.1);
    item->updateCoordinate();
    return item;
}

void GraphicsLineItem::addPoint(const QPointF &point)
{
    m_points.append(mapFromScene(point));
    int dir = m_points.count();
    SizeHandleRect *shr = new SizeHandleRect(this, dir+Left, dir == 1 ? false : true);
    shr->setState(SelectionHandleActive);
    m_handles.push_back(shr);
}


void GraphicsLineItem::endPoint(const QPointF &point)
{
    Q_UNUSED(point);
    int nPoints = m_points.count();
    if( nPoints > 2 && (m_points[nPoints-1] == m_points[nPoints-2] ||
        m_points[nPoints-1].x() - 1 == m_points[nPoints-2].x() &&
        m_points[nPoints-1].y() == m_points[nPoints-2].y())){
        delete m_handles[ nPoints-1];
        m_points.remove(nPoints-1);
        m_handles.resize(nPoints-1);
    }
    m_initialPoints = m_points;
}

QPointF GraphicsLineItem::opposite(int handle)
{
    QPointF pt;
    switch (handle)
    {
        case Right:
        case Left:
        case Top:
        case LeftTop:
        case RightTop:
            pt = m_handles[1]->pos();
            break;
        case RightBottom:
        case LeftBottom:
        case Bottom:
            pt = m_handles[0]->pos();
            break;
     }
    return pt;
}

void GraphicsLineItem::stretch(int handle, double sx, double sy, const QPointF &origin)
{
    QTransform trans;
    switch (handle)
    {
        case Right:
        case Left:
            sy = 1;
            break;
        case Top:
        case Bottom:
            sx = 1;
            break;
        default:
            break;
    }
    trans.translate(origin.x(),origin.y());
    trans.scale(sx,sy);
    trans.translate(-origin.x(),-origin.y());

    prepareGeometryChange();
    m_points = trans.map(m_initialPoints);
    m_localRect = m_points.boundingRect();
    m_width = m_localRect.width();
    m_height = m_localRect.height();
    updatehandles();
}

void GraphicsLineItem::updatehandles()
{
    for ( int i = 0 ; i < m_points.size() ; ++i ){
        m_handles[i]->move(m_points[i].x() ,m_points[i].y() );
    }
}

void GraphicsLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    painter->setPen(pen());
    if ( m_points.size() > 1)
    painter->drawLine(m_points.at(0),m_points.at(1));
}

GraphicsConnectLineItem::GraphicsConnectLineItem(QGraphicsItem *parent)
    :QGraphicsLineItem(parent)
    ,m_pivotTool(new ConnectLineItemPivotTool())
    ,m_isSelected(false)
    ,m_midRects(new QList<ConnectLineMidRect*>())
{
    //setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
}

bool GraphicsConnectLineItem::isNearPoint(const QPointF &pos, const QPointF &point) const
{
    QRectF handleRect(point.x() - 10, point.y() - 10, 20, 20);
    return handleRect.contains(pos);
}

QPainterPath GraphicsConnectLineItem::shape() const
{
    QPainterPath path;
    path.moveTo(m_pivotTool->getStartPoint());
    for(auto it : m_pivotTool->getPivotPoints())
        path.lineTo(it);
    path.lineTo(m_pivotTool->getEndPoint());

    QPainterPathStroker stroker;
    stroker.setWidth(20); // 设置点击区域的扩展宽度
    return stroker.createStroke(path);
}

void GraphicsConnectLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    if(m_pivotTool->getEndPoint().isNull())
        return;

    QPen pen = this->pen();
    if (m_isSelected)
    {
        pen.setColor(Qt::red);
        pen.setWidthF(2.5);
    }

    painter->setPen(pen);
    QPointF startPoint(m_pivotTool->getStartPoint());
    QPointF endPoint;
    for(auto it : m_pivotTool->getPivotPoints())
    {
        endPoint = it;
        QLineF connectLine(startPoint, endPoint);
        painter->drawLine(connectLine);
        startPoint = endPoint;
    }
    endPoint = m_pivotTool->getEndPoint();
    QLineF connectLine(startPoint, endPoint);
    painter->drawLine(connectLine);

    if (connectLine.length() > 0)
    {
        const qreal arrowSize = 10;
        double angle = std::atan2(connectLine.dy(), -connectLine.dx());
        QPointF arrowP1 = connectLine.p2() + QPointF(sin(angle + M_PI / 3) * arrowSize,
                                                        cos(angle + M_PI / 3) * arrowSize);
        QPointF arrowP2 = connectLine.p2() + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
                                                        cos(angle + M_PI - M_PI / 3) * arrowSize);
        painter->setBrush(pen.color());
        painter->drawPolygon(QPolygonF() << connectLine.p2() << arrowP1 << arrowP2);
    }

    //    if (m_isSelected)
    //    {
    //        painter->fillRect(QRectF(m_pivotTool->getStartPoint().x() - 3, m_pivotTool->getStartPoint().y() - 3, 6, 6), Qt::blue);
    //        painter->fillRect(QRectF(m_pivotTool->getEndPoint().x() - 3, m_pivotTool->getEndPoint().y() - 3, 6, 6), Qt::blue);
    //    }
}

QVariant GraphicsConnectLineItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    if (change == ItemSelectedHasChanged)
    {
        m_isSelected = value.toBool();
        for(auto it : *m_midRects)
            m_isSelected ? it->show() : it->hide();
    }
    return QGraphicsLineItem::itemChange(change, value);
}

QRectF GraphicsConnectLineItem::boundingRect() const
{
    return shape().boundingRect();
}

void GraphicsConnectLineItem::initMidRects()
{
    m_midRects->clear();
    QList<QPointF*> pivotPoints;
    pivotPoints.append(&m_pivotTool->getStartPoint());
    for(auto& it : m_pivotTool->getPivotPoints())
        pivotPoints.append(&it);
    pivotPoints.append(&m_pivotTool->getEndPoint());

    for(size_t i =0; i < pivotPoints.size(); i++)
    {
        if(i == 0)
            continue;
        ConnectLineMidRect* midRect = new ConnectLineMidRect(this, pivotPoints[i - 1], pivotPoints[i]);
        m_midRects->append(midRect);
    }
}

void ConnectLineItemPivotTool::calculatePivotPoints(PinPointHandle* pin, QPointF endPoint)
{
    if(m_startPoint.isNull())
        return;

    Direction dir = DirectionConverter::toDirection(pin->getPin().dir);
    m_pivotPoints.clear();
    m_endPoint = endPoint;

    if(m_endPin)
        endPoint = getEndPinOffsetPoint(m_endPin);

    if(isEndPointInShape(endPoint))
    {
        m_endPoint = m_startPoint;
        m_endPin = nullptr;
        return;
    }

    if(isEndPointInPinDirection(dir, endPoint))
        dealEndPointInPinDirection(dir, endPoint);
    if(isEndPointInCrossDirections(dir, endPoint))
        dealEndPointInCrossDirections(dir, endPoint);
    if(isEndPointInPinOppositeDirection(dir, endPoint))
        dealEndPointInPinOppositeDirection(dir,endPoint);

    if(m_endPin)
    {
        m_pivotPoints.append(getEndPinOffsetPoint(m_endPin));
        dealCrossConnectLine();
        checkPivotPoints();
    }
}

QPointF ConnectLineItemPivotTool::getEndPinOffsetPoint(PinPointHandle* endPin)
{
    if(m_startPoint.isNull())
        return QPointF();

    Direction dir = DirectionConverter::toDirection(endPin->getPin().dir);
    QPointF targetPinPoint = m_startPin->parentItem()->mapFromScene(endPin->scenePos());

    switch (dir)
    {
        case Direction::Right:
            return QPointF(targetPinPoint + QPointF(m_extraInterval, 0));
        case Direction::Left:
            return QPointF(targetPinPoint - QPointF(m_extraInterval, 0));
        case Direction::Up:
            return QPointF(targetPinPoint + QPointF(0, m_extraInterval));
        case Direction::Down:
            return QPointF(targetPinPoint - QPointF(0, m_extraInterval));;
        default:
            return QPointF();
    }
}

bool ConnectLineItemPivotTool::isEndPointInShape(QPointF endPoint)
{
    if(!m_startPin || !m_startPin->parentItem())
        return false;

    return m_startPin->parentItem()->contains(endPoint) ? true : false;
}

bool ConnectLineItemPivotTool::isEndPointInPinDirection(Direction pindir, QPointF endPoint)
{
    if(!m_startPin || !m_startPin->parentItem())
        return false;

    QPointF basePoint = m_startPoint;
    switch (pindir)
    {
        case Direction::Right:
            return (endPoint.x() > basePoint.x());
        case Direction::Left:
            return (endPoint.x() < basePoint.x());
        case Direction::Up:
            return (endPoint.y() > basePoint.y());
        case Direction::Down:
            return (endPoint.y() < basePoint.y());
        default:
            return false;
    }
}

void ConnectLineItemPivotTool::dealEndPointInPinDirection(Direction pindir, QPointF endPoint)
{
    switch (pindir)
    {
        case Direction::Right:
        case Direction::Left:
            m_pivotPoints.append(QPointF(endPoint.x(), m_startPoint.y()));
            break;
        case Direction::Up:
        case Direction::Down:
            m_pivotPoints.append(QPointF(m_startPoint.x(), endPoint.y()));
            break;
    }
}

bool ConnectLineItemPivotTool::isEndPointInCrossDirections(Direction pindir, QPointF endPoint)
{
    if(!m_startPin || !m_startPin->parentItem())
        return false;

    QRectF rect = m_startPin->getParentRect();
    QPointF basePoint = m_startPoint;
    switch (pindir)
    {
        case Direction::Right:
            return (endPoint.x() <= basePoint.x() &&
                    (endPoint.y() <= rect.y() || endPoint.y() >= rect.y() + rect.height()));
        case Direction::Left:
            return (endPoint.x() >= basePoint.x() &&
                    (endPoint.y() <= rect.y() || endPoint.y() >= rect.y() + rect.height()));
        case Direction::Up:
            return (endPoint.y() <= basePoint.y() &&
                    (endPoint.x() <= rect.x() || endPoint.x() >= rect.x() + rect.width()));
        case Direction::Down:
            return (endPoint.y() >= basePoint.y() &&
                    (endPoint.x() <= rect.x() || endPoint.x() >= rect.x() + rect.width()));
        default:
            return false;
    }
}

void ConnectLineItemPivotTool::dealEndPointInCrossDirections(Direction pindir, QPointF endPoint)
{
    switch (pindir)
    {
        case Direction::Right:
            m_pivotPoints.append(QPointF(m_startPoint.x() + m_extraInterval, m_startPoint.y()));
            m_pivotPoints.append(QPointF(m_startPoint.x() + m_extraInterval, endPoint.y()));
            break;
        case Direction::Left:
            m_pivotPoints.append(QPointF(m_startPoint.x() - m_extraInterval, m_startPoint.y()));
            m_pivotPoints.append(QPointF(m_startPoint.x() - m_extraInterval, endPoint.y()));
            break;
        case Direction::Up:
            m_pivotPoints.append(QPointF(m_startPoint.x(), m_startPoint.y() + m_extraInterval));
            m_pivotPoints.append(QPointF(endPoint.x(), m_startPoint.y() + m_extraInterval));
            break;
        case Direction::Down:
            m_pivotPoints.append(QPointF(m_startPoint.x(), m_startPoint.y() - m_extraInterval));
            m_pivotPoints.append(QPointF(endPoint.x(), m_startPoint.y() - m_extraInterval));
            break;
    }
}

bool ConnectLineItemPivotTool::isEndPointInPinOppositeDirection(Direction pindir, QPointF endPoint)
{
    if(!m_startPin || !m_startPin->parentItem())
        return false;

    QRectF rect = m_startPin->getParentRect();
    switch (pindir)
    {
        case Direction::Right:
            return (endPoint.x() <= rect.x() &&
                    (endPoint.y() >= rect.y() && endPoint.y() <= rect.y() + rect.height()));
        case Direction::Left:
            return (endPoint.x() >= rect.x() + rect.width() &&
                    (endPoint.y() >= rect.y() && endPoint.y() <= rect.y() + rect.height()));
        case Direction::Up:
            return (endPoint.y() <= rect.y() &&
                    (endPoint.x() >= rect.x() && endPoint.x() <= rect.x() + rect.width()));
        case Direction::Down:
            return (endPoint.y() >= rect.y() + rect.height() &&
                    (endPoint.x() >= rect.x() && endPoint.x() <= rect.x() + rect.width()));
        default:
            return false;
    }
}

void ConnectLineItemPivotTool::dealEndPointInPinOppositeDirection(Direction pindir, QPointF endPoint)
{
    QRectF rect = m_startPin->getParentRect();
    bool isUpRange = endPoint.y() < (rect.y() + rect.height() / 2);
    bool isLeftRange = endPoint.x() < (rect.x() + rect.width() / 2);
    qreal rectVPointY = isUpRange ? rect.y() - m_extraInterval : rect.y() + rect.height() + m_extraInterval;
    qreal rectHPointX = isLeftRange ? rect.x() - m_extraInterval : rect.x() + rect.width() + m_extraInterval;
    switch (pindir)
    {
        case Direction::Right:
            m_pivotPoints.append(QPointF(m_startPoint.x() + m_extraInterval, m_startPoint.y()));
            m_pivotPoints.append(QPointF(m_startPoint.x() + m_extraInterval, rectVPointY));
            m_pivotPoints.append(QPointF(endPoint.x(), rectVPointY));
            break;
        case Direction::Left:
            m_pivotPoints.append(QPointF(m_startPoint.x() - m_extraInterval, m_startPoint.y()));
            m_pivotPoints.append(QPointF(m_startPoint.x() - m_extraInterval, rectVPointY));
            m_pivotPoints.append(QPointF(endPoint.x(), rectVPointY));
            break;
        case Direction::Up:
            m_pivotPoints.append(QPointF(m_startPoint.x(), m_startPoint.y() + m_extraInterval));
            m_pivotPoints.append(QPointF(rectHPointX, m_startPoint.y() + m_extraInterval));
            m_pivotPoints.append(QPointF(rectHPointX, endPoint.y()));
            break;
        case Direction::Down:
            m_pivotPoints.append(QPointF(m_startPoint.x(), m_startPoint.y() - m_extraInterval));
            m_pivotPoints.append(QPointF(rectHPointX, m_startPoint.y() - m_extraInterval));
            m_pivotPoints.append(QPointF(rectHPointX, endPoint.y()));
            break;
    }
}

void ConnectLineItemPivotTool::dealEndPointInEndShape()
{
}

//找到交点
static QList<QPointF> getOrderedIntersections(const QLineF& line, const QRectF& rect)
{
    QList<QPointF> intersections;
    const QVector<QLineF> edges
    {
        QLineF(rect.topLeft(), rect.topRight()),    // 上边
        QLineF(rect.topRight(), rect.bottomRight()),// 右边
        QLineF(rect.bottomRight(), rect.bottomLeft()),// 下边
        QLineF(rect.bottomLeft(), rect.topLeft())   // 左边
    };

    for (const QLineF& edge : edges) {
        QPointF intersect;
        if (line.intersect(edge, &intersect) == QLineF::BoundedIntersection)
            intersections.append(intersect);
    }

    // 按到起点的距离排序
    std::sort(intersections.begin(), intersections.end(),
        [&](const QPointF& a, const QPointF& b) {
            return QLineF(line.p1(), a).length() < QLineF(line.p1(), b).length();
        });

    return intersections;
}

static QPointF findCorrespondRectVertex(QPointF point, QRectF rect)
{
    QPointF center = rect.center();
    bool right = point.x() > center.x();
    bool bottom = point.y() > center.y();
    QPointF newPoint;
    if (right)
        newPoint = bottom ? rect.bottomRight() : rect.topRight();
    else
        newPoint = bottom ? rect.bottomLeft() : rect.topLeft();
    return newPoint;
}

static QPointF findCorrespondPointFormTreePoint(QPointF point, QPointF in, QPointF out)
{
    QPointF ret(in.x() + out.x() - point.x(), in.y() + out.y() - point.y());
    return ret;
}

void ConnectLineItemPivotTool::dealCrossConnectLine()
{
    QList<QPointF> allPoints;
    allPoints.append(m_startPoint);
    allPoints.append(m_pivotPoints);
    allPoints.append(m_endPoint);

    if(!m_endPin)
        return;
    QGraphicsItem* startRect = m_startPin->parentItem();
    QGraphicsItem* endRect = m_endPin->parentItem();
    QRectF endPinRect = startRect->mapRectFromItem(endRect, endRect->boundingRect());
    QRectF avoidRect = endPinRect.adjusted(-m_extraInterval, -m_extraInterval, m_extraInterval, m_extraInterval);

    // 情况1：终点在矩形内 暂时不做 找不到endshape
    // 情况2：终点在矩形外 有点在shape内
    for(int i = 0; i < allPoints.size() - 1;)
    {
        if(!avoidRect.contains(allPoints[i]) || i == 0)
        {
            i++;
            continue;
        }

        QLineF LineEnter(allPoints[i - 1], allPoints[i]);
        QList<QPointF> intersectsEnter = getOrderedIntersections(LineEnter, avoidRect);
        QLineF LineLeave(allPoints[i], allPoints[i + 1]);
        QList<QPointF> intersectsLeave = getOrderedIntersections(LineLeave, avoidRect);
        if(intersectsEnter.isEmpty() ||intersectsLeave.isEmpty())
        {
            i++;
            continue;
        }

        //需要增加的新点
        QPointF newPoint = findCorrespondPointFormTreePoint(allPoints[i], intersectsEnter[0], intersectsLeave[0]);

        allPoints.removeAt(i);
        allPoints.insert(i, intersectsEnter[0]);
        allPoints.insert(i + 1, newPoint);
        allPoints.insert(i + 2, intersectsLeave[0]);
        i += 3;
    }

    // 情况3：终点在矩形外 连线穿过矩形
    for (int i = 0; i < allPoints.size() - 1;) {
        QLineF currentLine(allPoints[i], allPoints[i+1]);
        QList<QPointF> intersects = getOrderedIntersections(currentLine, avoidRect);
        if (intersects.size() != 2 || intersects[0].isNull() || intersects[1].isNull())
        {
            i++;
            continue;
        }

        //需要增加的新点
        QPointF newPointEnter = findCorrespondRectVertex(intersects[0], avoidRect);
        QPointF newPointLeave = findCorrespondRectVertex(intersects[1], avoidRect);

        allPoints.removeAt(i+1);
        allPoints.insert(i+1, intersects[0]);
        allPoints.insert(i+2, newPointEnter);
        allPoints.insert(i+3, newPointLeave);
        allPoints.insert(i+4, intersects[1]);
        i += 5;
    }

    if(m_pivotPoints.size() == allPoints.size() - 2)
        return ;

    m_pivotPoints.clear();
    for(int i = 0; i < allPoints.size(); i++)
    {
        if(i ==0 || i == allPoints.size() - 1)
          continue;
        m_pivotPoints.append(allPoints[i]);
    }
}

void ConnectLineItemPivotTool::checkPivotPoints()
{
    QList<QPointF> allPoints;
    allPoints.append(m_startPoint);
    allPoints.append(m_pivotPoints);
    allPoints.append(m_endPoint);

    // 优化条件2：删除相同点之间的所有点
    int i = 0;
    while (i < allPoints.size()) {
        bool found = false;
        for (int j = i + 1; j < allPoints.size(); ++j) {
            if (allPoints[i] == allPoints[j]) {
                // 删除i+1到j的点
                int removeCount = j - i;
                for (int k = 0; k < removeCount; ++k) {
                    allPoints.removeAt(i + 1);
                }
                found = true;
                break;
            }
        }
        if (!found) {
            ++i;
        }
    }

    // 优化条件1：删除连续共线中的中间点
    bool modified;
    do {
        modified = false;
        for (int i = 0; i < allPoints.size() - 2; ++i) {
            const QPointF& p0 = allPoints[i];
            const QPointF& p1 = allPoints[i + 1];
            const QPointF& p2 = allPoints[i + 2];
            // 计算叉积判断是否共线
            qreal cross = (p1.x() - p0.x()) * (p2.y() - p0.y())
                        - (p1.y() - p0.y()) * (p2.x() - p0.x());
            if (qFuzzyIsNull(cross)) { // 使用Qt的浮点精度判断
                allPoints.removeAt(i + 1);
                modified = true;
                --i; // 调整索引以重新检查当前位置
            }
        }
    } while (modified);

    m_pivotPoints.clear();
    for(int i = 0; i < allPoints.size(); i++)
    {
        if(i ==0 || i == allPoints.size() - 1)
          continue;
        m_pivotPoints.append(allPoints[i]);
    }
}

